package eiisan.lucenedemo;

import org.apache.commons.io.FileUtils;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.*;
import org.apache.lucene.queryparser.surround.parser.ParseException;
import org.apache.lucene.search.*;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.junit.Test;
import org.wltea.analyzer.lucene.IKAnalyzer;

import java.io.File;
import java.io.IOException;

/**
 * @description:
 * @author: eii
 * @time: 2020/8/7 9:05 下午
 */
public class LuceneFirst {

    /**
     * 创建索引
     * 1、创建一个Director付象，指定索引库保存的位置
     * 2、基于Directory対象創建一个 IndexWriter対象
     * 3、读取磁盘上的文件，对应毎个文件创建个文档対象
     * 4、向文档対象中添加域
     * 5、把文档対象写入索引库
     * 6、关闭indexwriter对象
     *
     * @throws IOException
     */
    @Test
    public void createIndex() throws IOException {
        // 索引库放内存
        // Directory index = new RAMDirectory();
        // 1.索引库放磁盘
        Directory directory = FSDirectory.open(new File("/Users/eii/tmp/index").toPath());
        // 2 基于directory 创建一个IndexWriter
        IndexWriter indexWriter = new IndexWriter(directory, new IndexWriterConfig());
        File dir = new File("/Volumes/mdate/lucene/02.参考资料/searchsource");
        File[] files = dir.listFiles();
        for (File file : files) {
            String fileName = file.getName();
            String filePath = file.getPath();
            String fileContent = FileUtils.readFileToString(file, "utf-8");
            //文件大小
            long fileSize = FileUtils.sizeOf(file);
            //创建field
            Field fieldName = new TextField("name", fileName, Field.Store.YES);
            Field fieldPath = new TextField("path", filePath, Field.Store.YES);
            Field fieldContent = new TextField("content", fileContent, Field.Store.YES);
            Field fieldSize = new TextField("size", fileSize + "", Field.Store.YES);
            //创建文档对象
            Document doc = new Document();
            doc.add(fieldName);
            doc.add(fieldPath);
            doc.add(fieldContent);
            doc.add(fieldSize);
            //把文档对象写入索引库
            indexWriter.addDocument(doc);
        }
        //关闭 indexWriter对象
        indexWriter.close();
    }

    /**
     * 查询索引库
     * 1、创建一个Director对象，指定索引库的位置
     * 2、创建一个IndexReader对象
     * 3、创建一个IndexSearcher对象， 构造方法中的参数indexReader对象。
     * 4、创建一个Query对象，TermQuery
     * 5、执行查询，得到一个TopDocs对象
     * 6、取查询结果的总记录数
     * 7、取文档列表
     * 8、打印文档中的内容
     * 9、关闭IndexReader对象
     *
     * @throws ParseException
     */
    @Test
    public void indexReader() throws ParseException, IOException {
        Directory directory = FSDirectory.open(new File("/Users/eii/tmp/index").toPath());
        IndexReader reader = DirectoryReader.open(directory);
        IndexSearcher indexSearcher = new IndexSearcher(reader);
        String querystr = "lucene";
//        Query query = new TermQuery(new Term("content", "spring"));
//        Query query = new TermQuery(new Term("name", "全文"));   // "全文"查询不到，因为此时的默认分词，没能正确分中文词组
        Query query = new TermQuery(new Term("name", "文"));
        int hitsPerPage = 10;
        TopDocs topDocs = indexSearcher.search(query, hitsPerPage);
        System.out.println("查询总记录数：" + topDocs.totalHits);
        ScoreDoc[] scoreDocs = topDocs.scoreDocs;
        for (ScoreDoc scoreDoc : scoreDocs) {
            int docId = scoreDoc.doc;
            Document document = indexSearcher.doc(docId);
            System.out.println("name: " + document.get("name"));
            System.out.println("path: " + document.get("path"));
            System.out.println("content: " + document.get("content"));
            System.out.println("size:" + document.get("size"));
            System.out.println("---------------------------");
        }
        reader.close();
    }

    /**
     * 分析器
     * 1 创建一个Analyzer对象，StandardAnalyzer对 象
     * 2 使用分析器对象的tokenStream方法获得一个 TokenStream对象
     * 3 向TokenStream对象中设置一个引用，相当于数一个指针
     * 4 调用TokenStream对象的rest方法。
     * 5 使用while循环遍历TokenStream对象
     * 6 关闭TokenStream对象
     */
    @Test
    public void testTokenStream() throws IOException {
        Analyzer analyzer = new StandardAnalyzer();  //默认的分词器，无法对中文进行分析
        String fileName = "测试文件";
        String text = "Lucene先在内存中进行索引操作，并根据一定的批量进行文件的写入。这个批次的间隔越大，文件的写入次数越少，但占用内存会很多。反之占用内存少，但文件IO操作频繁，索引速度会很慢。在IndexWriter中有一个MERGE_FACTOR参数可以帮助你在构造索引器后根据应用环境的情况充分利用内存减少文件的操作。根据我的使用经验：缺省Indexer是每20条记录索引后写入一次，每将MERGE_FACTOR增加50倍，索引速度可以提高1倍左右。";
        TokenStream tokenStream = analyzer.tokenStream(fileName, text);
        CharTermAttribute charTermAttribute = tokenStream.addAttribute(CharTermAttribute.class);
        tokenStream.reset();
        while (tokenStream.incrementToken()){
            System.out.println(charTermAttribute.toString());
        }
        tokenStream.close();
    }

    /**
     * IK 分词器对使用
     * 1 把IKAnalyzer的jar包添加到工程中
     * 2 把配置文件和扩展词典添加到工程的classpath下
     * 注意:扩展词典严禁使用windows记事本编辋保证扩展词典的编码格式是utf-8
     * 扩展词典:添加一些新词
     * 停用词词典:无意义的词或者是敏感词汇
     */
    @Test
    public void testIKAnalyzer() throws IOException {
        Analyzer analyzer = new IKAnalyzer();  //默认的分词器，无法对中文进行分析
        String fileName = "测试文件";
        String text = "Lucene先在内存中进行索引操作，并根据一定的批量进行文件的写入。这个批次的间隔越大，文件的写入次数越少，但占用内存会很多。反之占用内存少，但文件IO操作频繁，索引速度会很慢。在IndexWriter中有一个MERGE_FACTOR参数可以帮助你在构造索引器后根据应用环境的情况充分利用内存减少文件的操作。根据我的使用经验：缺省Indexer是每20条记录索引后写入一次，每将MERGE_FACTOR增加50倍，索引速度可以提高1倍左右。";
        TokenStream tokenStream = analyzer.tokenStream(fileName, text);
        CharTermAttribute charTermAttribute = tokenStream.addAttribute(CharTermAttribute.class);
        tokenStream.reset();
        while (tokenStream.incrementToken()){
            System.out.println(charTermAttribute.toString());
        }
        tokenStream.close();
    }



}
